using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Volo.Abp.DependencyInjection;
using Volo.Abp.EventBus.Local;
using Volo.Abp.Timing;
using Matrix.Configuration.Events;
using Matrix.Configuration.Services;

namespace Matrix.Application.Services
{
    /// <summary>
    /// 简化版配置事件分发器实现
    /// 专注于本地事件处理，暂时移除分布式事件功能
    /// </summary>
    public class ConfigurationEventDistributor : IConfigurationEventDistributor, ITransientDependency
    {
        private readonly ILocalEventBus _localEventBus;
        private readonly ILogger<ConfigurationEventDistributor> _logger;
        private readonly IClock _clock;

        public ConfigurationEventDistributor(
            ILocalEventBus localEventBus,
            ILogger<ConfigurationEventDistributor> logger,
            IClock clock)
        {
            _localEventBus = localEventBus;
            _logger = logger;
            _clock = clock;
        }

        public async Task PublishConfigurationChangedAsync(ConfigurationChangedEto eventData)
        {
            if (eventData == null)
            {
                throw new ArgumentNullException(nameof(eventData));
            }

            try
            {
                // 确保事件ID存在
                if (eventData.EventId == Guid.Empty)
                {
                    eventData.EventId = Guid.NewGuid();
                }

                // 设置事件时间
                eventData.EventTime = _clock.Now;

                _logger.LogDebug(
                    "发布配置变更本地事件: {EventId}, Key: {Key}, Namespace: {Namespace}",
                    eventData.EventId,
                    eventData.Key,
                    eventData.Namespace);

                // 发布本地事件
                var localEvent = new ConfigurationChangedLocalEvent(eventData);
                await _localEventBus.PublishAsync(localEvent);

                _logger.LogDebug("配置变更本地事件已发布: {EventId}", eventData.EventId);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "发布配置变更事件失败: {EventId}, Key: {Key}",
                    eventData.EventId, eventData.Key);
                throw;
            }
        }

        public async Task PublishConfigurationBatchChangedAsync(ConfigurationBatchChangedEto batchEventData)
        {
            if (batchEventData == null)
            {
                throw new ArgumentNullException(nameof(batchEventData));
            }

            try
            {
                // 确保批量事件ID存在
                if (batchEventData.BatchEventId == Guid.Empty)
                {
                    batchEventData.BatchEventId = Guid.NewGuid();
                }

                // 设置事件时间
                batchEventData.EventTime = _clock.Now;

                _logger.LogDebug(
                    "发布批量配置变更本地事件: {BatchEventId}, Changes: {ChangeCount}",
                    batchEventData.BatchEventId,
                    batchEventData.Changes.Count);

                // 发布本地事件
                var localEvent = new ConfigurationBatchChangedLocalEvent(batchEventData);
                await _localEventBus.PublishAsync(localEvent);

                _logger.LogDebug("批量配置变更本地事件已发布: {BatchEventId}", batchEventData.BatchEventId);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "发布批量配置变更事件失败: {BatchEventId}",
                    batchEventData.BatchEventId);
                throw;
            }
        }

        public async Task PublishCacheInvalidatedAsync(
            List<string> cacheKeys,
            string configurationKey,
            string @namespace,
            string reason,
            bool isDistributedCache = false,
            Guid? tenantId = null)
        {
            if (cacheKeys == null || !cacheKeys.Any())
            {
                return;
            }

            try
            {
                var localEvent = new ConfigurationCacheInvalidatedLocalEvent
                {
                    CacheKeys = cacheKeys,
                    ConfigurationKey = configurationKey,
                    Namespace = @namespace,
                    Reason = reason,
                    IsDistributedCache = isDistributedCache,
                    EventTime = _clock.Now,
                    TenantId = tenantId
                };

                // 缓存失效事件总是使用本地事件
                await _localEventBus.PublishAsync(localEvent);

                _logger.LogDebug(
                    "配置缓存失效事件已发布: Key: {Key}, CacheKeys: {CacheKeyCount}, Reason: {Reason}",
                    configurationKey,
                    cacheKeys.Count,
                    reason);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "发布配置缓存失效事件失败: Key: {Key}", configurationKey);
                throw;
            }
        }

        public async Task PublishValidationEventAsync(
            string key,
            string @namespace,
            string? value,
            string valueType,
            ConfigurationValidationResult validationResult,
            string triggeredBy,
            Guid? tenantId = null)
        {
            try
            {
                var localEvent = new ConfigurationValidationLocalEvent
                {
                    Key = key,
                    Namespace = @namespace,
                    Value = value,
                    ValueType = valueType,
                    ValidationResult = validationResult,
                    TriggeredBy = triggeredBy,
                    ValidationTime = _clock.Now,
                    TenantId = tenantId
                };

                // 验证事件总是使用本地事件
                await _localEventBus.PublishAsync(localEvent);

                _logger.LogDebug(
                    "配置验证事件已发布: Key: {Key}, IsValid: {IsValid}, TriggeredBy: {TriggeredBy}",
                    key,
                    validationResult.IsValid,
                    triggeredBy);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "发布配置验证事件失败: Key: {Key}", key);
                throw;
            }
        }
    }
}